<?php
require __DIR__."/init.php";
if(App::$mode != 'production'){
    header("Access-Control-Allow-Origin: *");;
    header("Access-Control-Allow-Headers: X-Requested-With,content-type,X-File-Name,Authorization");
    header("Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONS");
}
header("X-Powered-By: ASP.NET");
if($_SERVER["REQUEST_METHOD"] == "OPTIONS"){
    exit;
}
if(empty($_SERVER['PATH_INFO'])){
    $uri = $_SERVER['REQUEST_URI'];
    $info = parse_url($uri);
    $PATH_INFO = $info['path'];
}else{
    $PATH_INFO =  $_SERVER['PATH_INFO'];
}

$path = PATH_SRC_PHP.$PATH_INFO.".php";
$REQUEST_METHOD = strtolower($_SERVER['REQUEST_METHOD']);

class ErrHttp extends Exception{}
class Auth{
    static function gen_token($id,$logas){
        //ini_set('session.gc_maxlifetime', 11);
        session_regenerate_id(session_id());
        $_SESSION['auth'] = array(
            "id"=>$id,
            "logas"=>$logas,
        );
        return array(
            "token"=>"Bearer ".session_id()
        );
    }
}
function requireJosn($pathJson) {
    $contentText = file_get_contents($pathJson);
    return json_decode($contentText);
}
function get_role_permission(){
    $doc = getApiDoc();
    $paths = $doc->paths;
    $_tags = array();
    foreach($doc->tags as $tag) {
        $_tags[$tag->name] = $tag->description;
    }
    $groups = $doc->groups;

    $permissionNodes = array();
    $__tags = array();
    $_paths = array();
    $permissionData = array();
    foreach($paths as $pathUrl=>$value){
        foreach($value as $method => $obj){
            $tagName = $_tags[$obj->tags[0]];
            $tag = $obj->tags[0];
            if(empty($obj->permission)) continue;
            $_paths[$pathUrl][$method] = array(
                "title"=>$obj->summary,
                "method"=>$method,
                "url"=>$pathUrl,
                "tagName"=>$tagName,
                "tag"=>$tag
            );
            $permissionNodes[$pathUrl."|".$method] = true;
            $__tags[$tagName][] = $_paths[$pathUrl][$method];
        }
    }
    $_groups = array();
    foreach($groups as $groupTitle=>$val){
        $subRow = array();
        foreach($val as $tagTitle=>$val1){
            $_groups[$groupTitle][$tagTitle] = $__tags[$tagTitle];
            $subRow[] = array(
                "title"=>$tagTitle,
                "items"=>$__tags[$tagTitle]
            );
        }
        if(count($subRow) > 0){
            $permissionData[] = array(
                "title"=>$groupTitle,
                "items"=>$subRow
            );
        }

    }
    $row = array();
    $row['permissionNodes'] = $permissionNodes;
    $row['permissionData'] = $permissionData;
    $row['permissionDataItems'] = $_groups;
    return $row;
}
function getApiDoc() {
    $doc_dir = PATH_PROJECT."/doc/api";
    $API_BASE = requireJosn($doc_dir.'/base.json');
    $tags = requireJosn($doc_dir.'/tags.json');

    if(!empty($_SERVER['HTTP_X_NGINX_PROXY'])){
        $API_BASE->host = $_SERVER['HTTP_HOST'];
    }

    $API_BASE->tags = $tags->tags;
    $API_BASE->groups = $tags->groups;
    $API_BASE->definitions = requireJosn($doc_dir.'/definitions.json');
    $API_BASE->paths = array();

    $files = array_filter(glob($doc_dir."/paths".'/*?*'),function($file) {
        return (is_file($file));
    });

    foreach($files as $file ){
        $info = requireJosn($file);
        foreach($info as $key=>$value){
            $API_BASE->paths[$key] = $value;
        }
    }
    return $API_BASE;
}

try{
    $param = NULL;
    if(is_file($path)){
        include $path;
    }else{
        $t = explode("/",$PATH_INFO);
        $t1= array_pop($t);
        $PATH_INFO = $p = implode("/",$t);
        $path = PATH_SRC_PHP.$p.".php";
        if(is_file($path)){
            $param = $t1;
            include $path;
        }else{
            throw new Exception("Not Found",404);
        }
    }
    $className = "Api";
    $method = $REQUEST_METHOD;
    if(!class_exists($className)){
        throw new Exception("Bad Request",400);
    }else{
        $obj = new $className();
        if(!method_exists($obj,$method)){
            throw new Exception("Method Not Allowed",405);
        }
        if(isset($_SERVER['HTTP_AUTHORIZATION'])){
            $t = explode(" ",$_SERVER['HTTP_AUTHORIZATION']);
            if(count($t) == 2){
                session_id(array_pop($t));
            }
        }

        session_start();
        $auth = NULL;
        if(!in_array($PATH_INFO,App::$apiUnlessPaths)){
            if(empty($_SESSION["auth"])){
                throw new Exception("Unauthorized",401);
            }else{
                $auth = $_SESSION["auth"];
            }
        }

        header("Content-Type: application/json;charset=utf-8");
        $req = new stdClass();
        $req->method = $REQUEST_METHOD;
        $req->param  = $param;
        $req->auth   = $auth;
        $req->pathInfo   = $PATH_INFO;
        $req->body   = get_php_input_json(false);
        //ob_start();
        $res = call_user_func_array(array($obj, $method), array($req));
        //$ob = ob_get_clean();
        //$res->ob = App::$config;
        echo json_encode($res);
    }

}catch(Exception $e){
    static $_status = array(
        // Informational 1xx
        100 => 'Continue',
        101 => 'Switching Protocols',
        // Success 2xx
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        // Redirection 3xx
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Moved Temporarily ',  // 1.1
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        // 306 is deprecated but reserved
        307 => 'Temporary Redirect',
        // Client Error 4xx
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Timeout',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Request Entity Too Large',
        414 => 'Request-URI Too Long',
        415 => 'Unsupported Media Type',
        416 => 'Requested Range Not Satisfiable',
        417 => 'Expectation Failed',
        // Server Error 5xx
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Timeout',
        505 => 'HTTP Version Not Supported',
        509 => 'Bandwidth Limit Exceeded'
    );
    $code = $e->getCode();
    $message = $e->getMessage();
    header("Content-Type: application/json;charset=utf-8");
    if(in_array($code,array(400,401,403,404,405))){
        header('HTTP/1.1 '.$code.' '.$_status[$code]);
    }else{
        header('HTTP/1.1 500 '.$_status[500]);
    }
    echo json_encode(array(
        "errCode"=>$code,
        "message"=>$message,
    ));
}
